package edu.uwaterloo.bicycle.framework;

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Area;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.awt.image.BufferedImage;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.URL;

import javax.imageio.ImageIO;

public class ShapedFrameUtils {
  public static class Result {
    public Shape shape;
    public Image image;
    public Dimension size;

    Result() {
    }
  }

  static Shape contour(final BufferedImage i) {
    final int w = i.getWidth();
    final int h = i.getHeight();
    final Area s = new Area(new Rectangle(w, h));
    final Rectangle r = new Rectangle(0, 0, 1, 1);
    for (r.y = 0; r.y < h; r.y++) {
      System.out.println(r.y + "/" + h);
      for (r.x = 0; r.x < w; r.x++) {
        if ((i.getRGB(r.x, r.y) & 0xFF000000) != 0xFF000000) {
          s.subtract(new Area(r));
        }
      }
    }
    return s;
  }

  static Dimension fit(final Dimension in, final Dimension out) {
    double r;
    if (out.height / (double) out.width > in.height / (double) in.width) {
      r = out.width / (double) in.width;
    } else {
      r = out.height / (double) in.height;
    }
    final Dimension fit = new Dimension();
    fit.width = (int) (in.width * r);
    fit.height = (int) (in.height * r);
    return fit;
  }

  static double fitRatio(final Dimension in, final Dimension out) {
    double r;
    if (out.height / (double) out.width > in.height / (double) in.width) {
      r = out.width / (double) in.width;
    } else {
      r = out.height / (double) in.height;
    }
    return r;
  }

  static Shape load(final DataInput is) throws IOException {
    final GeneralPath gp = new GeneralPath(is.readInt());
    final double[] data = new double[6];
    CYC: while (true) {
      final int type = is.readInt();
      for (int i = 0; i < data.length; i++) {
        data[i] = is.readDouble();
      }
      switch (type) {
      case PathIterator.SEG_MOVETO:
        gp.moveTo(data[0], data[1]);
        break;
      case PathIterator.SEG_LINETO:
        gp.lineTo(data[0], data[1]);
        break;
      case PathIterator.SEG_QUADTO:
        gp.quadTo(data[0], data[1], data[2], data[3]);
        break;
      case PathIterator.SEG_CUBICTO:
        gp.curveTo(data[0], data[1], data[2], data[3], data[4], data[5]);
        break;
      case PathIterator.SEG_CLOSE:
        break CYC;
      }
    }
    return gp.createTransformedShape(null);
  }

 /* public static void main(final String[] args) throws Exception {
    //ShapedFrameUtils.prepare("girl", ShapedFrameUtils.class.getResource("girl.png"), new Dimension(500, 500));
    //ShapedFrameUtils.prepare("exit", ShapedFrameUtils.class.getResource("exit.png"), new Dimension(32, 32));
	  ShapedFrameUtils.prepare("comp4", ShapedFrameUtils.class.getResource("comp4.png"), new Dimension(500, 576));
	 // ShapedFrameUtils.prepare("bLeft", ShapedFrameUtils.class.getResource("bLeft.png"), new Dimension(125, 125));
	 // ShapedFrameUtils.prepare("bRight", ShapedFrameUtils.class.getResource("bRight.png"), new Dimension(125, 125));
  }*/

  public static void prepare(final String name, final URL urlimage, final Dimension size) throws Exception {
    final BufferedImage image = ShapedFrameUtils.scale(ImageIO.read(urlimage), size.width, size.height);
    final Shape shape = ShapedFrameUtils.contour(image);
    ImageIO.write(image, "png", new FileOutputStream(name + ".png"));
    ShapedFrameUtils.save(shape, new RandomAccessFile(name + ".shp", "rw"));
  }

  public static Result restore(final String name) throws Exception {
    final Result result = new Result();
    result.shape = ShapedFrameUtils.load(new RandomAccessFile(name + ".shp", "rw"));
    result.image = ImageIO.read(new File(name + ".png"));
    result.size = new Dimension(result.image.getWidth(null), result.image.getHeight(null));
    return result;
  }

  static void save(final Shape s, final DataOutput os) throws IOException {
    final PathIterator pi = s.getPathIterator(null);
    os.writeInt(pi.getWindingRule());
    System.out.println(pi.getWindingRule());
    while (!pi.isDone()) {
      final double[] coords = new double[6];
      final int type = pi.currentSegment(coords);
      os.writeInt(type);
      System.out.println(type);
      for (final double coord : coords) {
        os.writeDouble(coord);
        System.out.println(coord);
      }
      System.out.println("");
      pi.next();
    }
  }

  static BufferedImage scale(final BufferedImage i, final int width, final int height) {
    final Dimension fit = ShapedFrameUtils.fit(new Dimension(i.getWidth(), i.getHeight()), new Dimension(width, height));
    final int newWidth = fit.width;
    final int newHeight = fit.height;
    final BufferedImage original = i;
    final BufferedImage resized = new BufferedImage(newWidth, newHeight, original.getType());
    final Graphics2D g = resized.createGraphics();
    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    g.drawImage(original, 0, 0, newWidth, newHeight, 0, 0, original.getWidth(), original.getHeight(), null);
    g.dispose();
    return resized;
  }
}
